package structureDonnee;
import instruction.Affectation;
import instruction.FaireRienInstruction;
import instruction.Instruction;
import instruction.UpdateInstruction;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;

import verificateur.EnsembleVariable;

public class Block {

	Node mFirstNode;
	LinkedList<Node> mesLastNodes;

	//construire arbre par un String
	public Block(String s, EnsembleVariable ev){
		//block = inv \n instr \n ... instr \n inv \n @

		mFirstNode = new Node();
		mesLastNodes= new LinkedList<Node>();
		
		int niveux = 0;
		String ms = s;
		int i=-1; 
		int carLu;
		StringBuffer buffer = new StringBuffer();
				
		i++;carLu = s.charAt(i);
		
		//lire le premier invariant
		do{	carLu= s.charAt(i); buffer.append((char)carLu); i++; }while("\n".indexOf(s.charAt(i))==-1);
		ms = buffer.toString();
		buffer.delete(0,buffer.length());	

		mFirstNode.invariant = new Invariant(ms,ev);
		mFirstNode.instr = new Instruction(new FaireRienInstruction());

		i++;//
		//si la fin, mFirstNode.instr Updateinstruction
		if(s.charAt(i)==(int)'@'){
			Invariant mti = new Invariant(mFirstNode.invariant.listIne);
			mFirstNode.instr=new Instruction(new UpdateInstruction(mti));
			if(mesLastNodes.size()==0){	mesLastNodes.add(mFirstNode);}
			else{
				Node toAdd = new Node(mFirstNode);
				mesLastNodes.clear();
				mesLastNodes.add(toAdd);
			}
			return;
		}
		
		//lire le premir instr
		carLu = s.charAt(i);
		
		///////////////////////////////////////////////////////////////////////////////////////////////////////
		//lire affectation
		//
		if(carLu=='['){
			//lire affectation
			do{	carLu= s.charAt(i);	buffer.append((char)carLu);	i++; }while("\n".indexOf(s.charAt(i))==-1);
			ms = buffer.toString();
			buffer.delete(0,buffer.length());

			mFirstNode.instr  = new Instruction(new Affectation(ms,ev));

			i++;ms = s.substring(i);	//ms = string de block suivant	
			
			//block suivant
			Block blockSui = new Block(ms,ev);
			
			mFirstNode.suivants.clear();
			mFirstNode.suivants.add(blockSui.mFirstNode);			
			
			mesLastNodes.clear();
			for(Node toAdd: blockSui.mesLastNodes){
				if(!mesLastNodes.contains(toAdd))
					mesLastNodes.add(toAdd);
			}

		}
		
		//////////////////////////////////////////////////////////////////////////////////////
		//lire conditionnelle
		//
		if(carLu=='i'){//now carLu =t, if(c)
			niveux++; // pour lire en cas de plusieur if{}else{} or while(){} dans ce block
			//lire c dans if(c)
			i = i + 3; //"if(", for 'i' to 'after ('
			do{ carLu= s.charAt(i); buffer.append((char)carLu); i++;}while(")".indexOf(s.charAt(i))==-1); //lire c, i at ")"
			ms = buffer.toString();
			buffer.delete(0,buffer.length());
			Inequalite c = new Inequalite(ms,ev);

			//lire block ture
			i = i+3;// if(c){ \n block from ")" to next line
			do{	carLu= s.charAt(i);	buffer.append((char)carLu);	i++; 
				if(s.charAt(i)=='f') niveux++;if(s.charAt(i)=='l') niveux++;if(s.charAt(i)=='@')niveux--;
				//rencontre if n++;rencontre else n++; rencontre while n++;rencontre @,n--; en cas de plusieur if{}else{} or while(){} dans ce block
			}while( ("@".indexOf(s.charAt(i))==-1) | (niveux!=0) );
			//
			carLu = s.charAt(i);buffer.append((char)carLu);i++;//lire @
			String bt = buffer.toString();//bt = block true
			buffer.delete(0,buffer.length());
			
			//lire block false
			i = i+8 ;//{inv0} \n if(){\n blockture @} \n else{ \n blockfalse @} \n{inv3} \\from "}" to "blockfalse"
			niveux ++;
			do{	carLu= s.charAt(i);buffer.append((char)carLu);	i++; 
				if(s.charAt(i)=='f') niveux++;if(s.charAt(i)=='l') niveux++;if(s.charAt(i)=='@')niveux--;
				//rencontre if n++;rencontre while n++; rencontre else n++;rencontre @,n--;
			}while( ("@".indexOf(s.charAt(i))==-1) | (niveux!=0));
			carLu = s.charAt(i);buffer.append((char)carLu);i++;//lire @
			String bf = buffer.toString();//bf = block false
			buffer.delete(0,buffer.length());

			//lire block suivant
			i = i+2;// @} \n {inv3} from } to next line
			ms = s.substring(i);//ms string pour block suivant
			String mst = ms;
			String msf = ms;

			this.mFirstNode.suivants.clear();
			
			//creer Block Ture
			Block bTrue = new Block(bt,ev);	//from string bt = block true
			this.mFirstNode.suivants.add(bTrue.mFirstNode);
			//mettre a jour  environement de premier node de block ture : inv0 AND c;
			bTrue.mFirstNode.environ.listIne.addAll(this.mFirstNode.invariant.listIne);
			bTrue.mFirstNode.environ.listIne.add(c);
			//block after bTure: 
			Block bSuivantTrue = new Block(mst,ev);	//bs = block suivant de btrue
			//update block true. mesLastNodes
			int lT  = bTrue.mesLastNodes.size();
			for(Node tmp:bTrue.mesLastNodes) if(tmp.suivants!=null) tmp.suivants.clear();//clear list de mesLastNodes de blockTrue
			Node tmpNode = new Node();
			while(lT!=0){
				tmpNode = bTrue.mesLastNodes.remove();
				lT -- ;
				if(tmpNode.suivants!=null)tmpNode.suivants.add(bSuivantTrue.mFirstNode);
				for(Node toAdd : bSuivantTrue.mesLastNodes)
					if(! bTrue.mesLastNodes.contains(toAdd))
						bTrue.mesLastNodes.add(toAdd);
			}
			mesLastNodes.addAll(bTrue.mesLastNodes);
			
			//creer Block False
			Block bFalse = new Block(bf,ev);//from string bf = block false
			this.mFirstNode.suivants.add(bFalse.mFirstNode);
			//mettre a jour  environement de premier node de block false: inv0 AND (NOT c);
			bFalse.mFirstNode.environ.listIne.addAll(this.mFirstNode.invariant.listIne);
			bFalse.mFirstNode.environ.listIne.add(c.not());
			//block after bFalse: 
			Block bSuivantFalse = new Block(msf,ev);	//bf = block suivant de bfalse
			//update block false .mesLastNodes
			int lF  = bFalse.mesLastNodes.size();
			for(Node tmp:bFalse.mesLastNodes) tmp.suivants.clear();
			while(lF!=0){
				tmpNode = bFalse.mesLastNodes.remove();
				lF -- ;
				tmpNode.suivants.add(bSuivantFalse.mFirstNode);
				for(Node toAdd : bSuivantFalse.mesLastNodes)
					if(! bFalse.mesLastNodes.contains(toAdd))
						bFalse.mesLastNodes.add(toAdd);
			}
			mesLastNodes.addAll(bFalse.mesLastNodes);
		}
		
		
		//////////////////////////////////////////////////////////////////////
		//lire boucle while(c){}
		//
		//
		if(carLu == 'w'){
			niveux++;

			//lire c dans while(c){}
			i = i + 6; //"while(", for 'w' to 'after ('
			do{	carLu= s.charAt(i);	buffer.append((char)carLu);	i++; }while(")".indexOf(s.charAt(i))==-1);
			ms = buffer.toString();
			buffer.delete(0,buffer.length());
			Inequalite c = new Inequalite(ms,ev);
						
			i = i+3;// while(c){ \n block from ')' to next line
			//lire block boucle
			do{	carLu= s.charAt(i);	buffer.append((char)carLu);	i++; 
				if(s.charAt(i)=='f') niveux++;if(s.charAt(i)=='l') niveux++;if(s.charAt(i)=='@')niveux--;
			}while( ("@".indexOf(s.charAt(i))==-1) | (niveux!=0) );
			//
			carLu = s.charAt(i);buffer.append((char)carLu);i++;//lire @, carLu =='}'
			ms = buffer.toString();
			String bb = ms; //bb = string de block boucle
			buffer.delete(0,buffer.length());
			
			//lire block suivant
			i = i+2;// @} \n {inv3} from } to next line
			ms = s.substring(i);
			String bs = ms;//string pour block suivant
			
			//creer Block boucle pour this
			Block bBoucle = new Block(bb,ev);	
			this.mFirstNode.suivants.add(bBoucle.mFirstNode);
			//mettre a jour  environement de premier node de block Boucle = inv0 AND c;
			bBoucle.mFirstNode.environ.listIne.addAll(this.mFirstNode.invariant.listIne); //first add inv0
			bBoucle.mFirstNode.environ.listIne.add(c); //then add c
			
			//block boucleSuivant pour this;
			Block bSuivant = new Block(bs,ev);	//bs = block suivant la boucle
			this.mFirstNode.suivants.add(bSuivant.mFirstNode);
			//mettre a jour  environement de premier node de block suivant la boucle = inv0 AND (NOT c);
			bSuivant.mFirstNode.environ.listIne.addAll(this.mFirstNode.invariant.listIne); //first add inv0
			bSuivant.mFirstNode.environ.listIne.add(c.not()); //then add c
			
			//pour chaque LastNode de Block boucle, creer :
			//1 creer boucle selon bs avec environ inv2 AND (NOT c) 
			//2 creer un Node avec envrion inv2 AND c invarant inv1
			
			for(Node tmpB: bBoucle.mesLastNodes) {//corriger instruction de block Boucle lastNodes de Update to FaireRien
				tmpB.instr = new Instruction(new FaireRienInstruction());
				if(tmpB.suivants!=null)	tmpB.suivants.clear();
			}
			int lS  = bBoucle.mesLastNodes.size();
			while(lS!=0){
				Node tmp = bBoucle.mesLastNodes.remove();
				lS -- ;
				//1 creer boucle selon bs avec environ inv2 AND (NOT c)
				Block bBoucleSuivant = new Block(bs,ev);
				if(tmp.suivants!=null) tmp.suivants.add(bBoucleSuivant.mFirstNode);
				//mettre a jour  environement de premier node de block boucle suivant = inv2 AND (NOT c);
				bBoucleSuivant.mFirstNode.environ.listIne.addAll(tmp.invariant.listIne); //first add inv2
				bBoucleSuivant.mFirstNode.environ.listIne.add(c.not()); //then add c
				
				//2 creer un Node avec envrion inv2 AND c invarant inv1
				Node nodeBoucleSuivant = new Node();				
				Invariant invSuiBlockBoucle= new Invariant(bBoucle.mFirstNode.invariant.listIne);
				nodeBoucleSuivant.invariant.listIne.addAll(invSuiBlockBoucle.listIne);
				nodeBoucleSuivant.environ.listIne.addAll(tmp.invariant.listIne);
				nodeBoucleSuivant.environ.listIne.add(c);
				nodeBoucleSuivant.instr = new Instruction(new FaireRienInstruction());
				nodeBoucleSuivant.suivants = null;
				if(tmp.suivants!=null) tmp.suivants.add(nodeBoucleSuivant);
				
				//update mesLastNodes pour block Boucle apres chaque fois creer des sous block
				for(Node toAdd : bBoucleSuivant.mesLastNodes)
					if(!bBoucle.mesLastNodes.contains(toAdd))
						bBoucle.mesLastNodes.add(toAdd);
				bBoucle.mesLastNodes.add(nodeBoucleSuivant);
			}
						
			//update mesLastNodes pour block 
			mesLastNodes.clear();
			mesLastNodes.addAll(bBoucle.mesLastNodes);
			mesLastNodes.addAll(bSuivant.mesLastNodes);
		}

		return;

	}

	

	//construire arbre par un nomficher.txt
	public Block(String nomficher) throws IOException{
		//lire des fichier to a String s;
		EnsembleVariable ev = new EnsembleVariable(nomficher);
		StringBuilder tbuffer = new StringBuilder(); // si plus, tant pis;
		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(nomficher),"UTF-8"));
		String line;
		line = reader.readLine();       // read the first line et le negliger
		
		line = reader.readLine();		//sauter the second line
		while (line != null) {          // if line == null,  finished 
			int indexString = -1;
			do{indexString++;}while((indexString<line.length())&(" \r\t".indexOf(line.charAt(indexString))!=-1));  //sauter white space     
            String s = line.substring(indexString);
			tbuffer.append(s);        // add the content to buffer
			tbuffer.append("\n");
            line = reader.readLine();   // next line
        }
        String s = tbuffer.toString();
        System.out.println(s);
        /////////////////////////////////////////////////////////////
        //code desous est meme que 
        //public Block(String s, EnsembleVariable ev)
        //////////////////////////////////////////////////////////
		//block = inv \n instr \n ... instr \n inv \n @
		//block = inv \n instr \n ... instr \n inv \n @

		mFirstNode = new Node();
		mesLastNodes= new LinkedList<Node>();
		
		int niveux = 0;
		String ms = s;
		int i=-1; 
		int carLu;
		StringBuffer buffer = new StringBuffer();
				
		i++;carLu = s.charAt(i);
		
		//lire le premier invariant
		do{	carLu= s.charAt(i); buffer.append((char)carLu); i++; }while("\n".indexOf(s.charAt(i))==-1);
		ms = buffer.toString();
		buffer.delete(0,buffer.length());	

		mFirstNode.invariant = new Invariant(ms,ev);
		mFirstNode.instr = new Instruction(new FaireRienInstruction());

		i++;//
		//si la fin, mFirstNode.instr Updateinstruction
		if(s.charAt(i)==(int)'@'){
			Invariant mti = new Invariant(mFirstNode.invariant.listIne);
			mFirstNode.instr=new Instruction(new UpdateInstruction(mti));
			if(mesLastNodes.size()==0){	mesLastNodes.add(mFirstNode);}
			else{
				Node toAdd = new Node(mFirstNode);
				mesLastNodes.clear();
				mesLastNodes.add(toAdd);
			}
			return;
		}
		
		//lire le premir instr
		carLu = s.charAt(i);
		
		///////////////////////////////////////////////////////////////////////////////////////////////////////
		//lire affectation
		//
		if(carLu=='['){
			//lire affectation
			do{	carLu= s.charAt(i);	buffer.append((char)carLu);	i++; }while("\n".indexOf(s.charAt(i))==-1);
			ms = buffer.toString();
			buffer.delete(0,buffer.length());

			mFirstNode.instr  = new Instruction(new Affectation(ms,ev));

			i++;ms = s.substring(i);	//ms = string de block suivant	
			
			//block suivant
			Block blockSui = new Block(ms,ev);
			
			mFirstNode.suivants.clear();
			mFirstNode.suivants.add(blockSui.mFirstNode);			
			
            mesLastNodes.clear();
			for(Node toAdd: blockSui.mesLastNodes){
				if(!mesLastNodes.contains(toAdd))
					mesLastNodes.add(toAdd);
			}

		}
		
		//////////////////////////////////////////////////////////////////////////////////////
		//lire conditionnelle
		//
		if(carLu=='i'){//now carLu =t, if(c)
			niveux++; // pour lire en cas de plusieur if{}else{} or while(){} dans ce block
			//lire c dans if(c)
			i = i + 3; //"if(", for 'i' to 'after ('
			do{ carLu= s.charAt(i); buffer.append((char)carLu); i++;}while(")".indexOf(s.charAt(i))==-1); //lire c, i at ")"
			ms = buffer.toString();
			buffer.delete(0,buffer.length());
			Inequalite c = new Inequalite(ms,ev);

			//lire block ture
			i = i+3;// if(c){ \n block from ")" to next line
			do{	carLu= s.charAt(i);	buffer.append((char)carLu);	i++; 
				if(s.charAt(i)=='f') niveux++;if(s.charAt(i)=='l') niveux++;if(s.charAt(i)=='@')niveux--;
				//rencontre if n++;rencontre else n++; rencontre while n++;rencontre @,n--; en cas de plusieur if{}else{} or while(){} dans ce block
			}while( ("@".indexOf(s.charAt(i))==-1) | (niveux!=0) );
			//
			carLu = s.charAt(i);buffer.append((char)carLu);i++;//lire @
			String bt = buffer.toString();//bt = block true
			buffer.delete(0,buffer.length());
			
			//lire block false
			i = i+8 ;//{inv0} \n if(){\n blockture @} \n else{ \n blockfalse @} \n{inv3} \\from "}" to "blockfalse"
			niveux ++;
			do{	carLu= s.charAt(i);buffer.append((char)carLu);	i++; 
				if(s.charAt(i)=='f') niveux++;if(s.charAt(i)=='l') niveux++;if(s.charAt(i)=='@')niveux--;
				//rencontre if n++;rencontre while n++; rencontre else n++;rencontre @,n--;
			}while( ("@".indexOf(s.charAt(i))==-1) | (niveux!=0));
			carLu = s.charAt(i);buffer.append((char)carLu);i++;//lire @
			String bf = buffer.toString();//bf = block false
			buffer.delete(0,buffer.length());

			//lire block suivant
			i = i+2;// @} \n {inv3} from } to next line
			ms = s.substring(i);//ms string pour block suivant
			String mst = ms;
			String msf = ms;

			this.mFirstNode.suivants.clear();
			
			//creer Block Ture
			Block bTrue = new Block(bt,ev);	//from string bt = block true
			this.mFirstNode.suivants.add(bTrue.mFirstNode);
			//mettre a jour  environement de premier node de block ture : inv0 AND c;
			bTrue.mFirstNode.environ.listIne.addAll(this.mFirstNode.invariant.listIne);
			bTrue.mFirstNode.environ.listIne.add(c);
			//block after bTure: 
			Block bSuivantTrue = new Block(mst,ev);	//bs = block suivant de btrue
			//update block true. mesLastNodes
			int lT  = bTrue.mesLastNodes.size();
			for(Node tmp:bTrue.mesLastNodes) if(tmp.suivants!=null) tmp.suivants.clear();//clear list de mesLastNodes de blockTrue
			Node tmpNode = new Node();
			while(lT!=0){
				tmpNode = bTrue.mesLastNodes.remove();
				lT -- ;
				if(tmpNode.suivants!=null)tmpNode.suivants.add(bSuivantTrue.mFirstNode);
				for(Node toAdd : bSuivantTrue.mesLastNodes)
					if(! bTrue.mesLastNodes.contains(toAdd))
						bTrue.mesLastNodes.add(toAdd);
			}
			mesLastNodes.addAll(bTrue.mesLastNodes);
			
			//creer Block False
			Block bFalse = new Block(bf,ev);//from string bf = block false
			this.mFirstNode.suivants.add(bFalse.mFirstNode);
			//mettre a jour  environement de premier node de block false: inv0 AND (NOT c);
			bFalse.mFirstNode.environ.listIne.addAll(this.mFirstNode.invariant.listIne);
			bFalse.mFirstNode.environ.listIne.add(c.not());
			//block after bFalse: 
			Block bSuivantFalse = new Block(msf,ev);	//bf = block suivant de bfalse
			//update block false .mesLastNodes
			int lF  = bFalse.mesLastNodes.size();
			for(Node tmp:bFalse.mesLastNodes) tmp.suivants.clear();
			while(lF!=0){
				tmpNode = bFalse.mesLastNodes.remove();
				lF -- ;
				tmpNode.suivants.add(bSuivantFalse.mFirstNode);
				for(Node toAdd : bSuivantFalse.mesLastNodes)
					if(! bFalse.mesLastNodes.contains(toAdd))
						bFalse.mesLastNodes.add(toAdd);
			}
			mesLastNodes.addAll(bFalse.mesLastNodes);
		}
		
		
		//////////////////////////////////////////////////////////////////////
		//lire boucle while(c){}
		//
		//
		if(carLu == 'w'){
			niveux++;

			//lire c dans while(c){}
			i = i + 6; //"while(", for 'w' to 'after ('
			do{	carLu= s.charAt(i);	buffer.append((char)carLu);	i++; }while(")".indexOf(s.charAt(i))==-1);
			ms = buffer.toString();
			buffer.delete(0,buffer.length());
			Inequalite c = new Inequalite(ms,ev);
						
			i = i+3;// while(c){ \n block from ')' to next line
			//lire block boucle
			do{	carLu= s.charAt(i);	buffer.append((char)carLu);	i++; 
				if(s.charAt(i)=='f') niveux++;if(s.charAt(i)=='l') niveux++;if(s.charAt(i)=='@')niveux--;
			}while( ("@".indexOf(s.charAt(i))==-1) | (niveux!=0) );
			//
			carLu = s.charAt(i);buffer.append((char)carLu);i++;//lire @, carLu =='}'
			ms = buffer.toString();
			String bb = ms; //bb = string de block boucle
			buffer.delete(0,buffer.length());
			
			//lire block suivant
			i = i+2;// @} \n {inv3} from } to next line
			ms = s.substring(i);
			String bs = ms;//string pour block suivant
			
			//creer Block boucle pour this
			Block bBoucle = new Block(bb,ev);	
			this.mFirstNode.suivants.add(bBoucle.mFirstNode);
			//mettre a jour  environement de premier node de block Boucle = inv0 AND c;
			bBoucle.mFirstNode.environ.listIne.addAll(this.mFirstNode.invariant.listIne); //first add inv0
			bBoucle.mFirstNode.environ.listIne.add(c); //then add c
			
			//block boucleSuivant pour this;
			Block bSuivant = new Block(bs,ev);	//bs = block suivant la boucle
			this.mFirstNode.suivants.add(bSuivant.mFirstNode);
			//mettre a jour  environement de premier node de block suivant la boucle = inv0 AND (NOT c);
			bSuivant.mFirstNode.environ.listIne.addAll(this.mFirstNode.invariant.listIne); //first add inv0
			bSuivant.mFirstNode.environ.listIne.add(c.not()); //then add c
			
			//pour chaque LastNode de Block boucle, creer :
			//1 creer boucle selon bs avec environ inv2 AND (NOT c) 
			//2 creer un Node avec envrion inv2 AND c invarant inv1
			
			for(Node tmpB: bBoucle.mesLastNodes) {//corriger instruction de block Boucle lastNodes de Update to FaireRien
				tmpB.instr = new Instruction(new FaireRienInstruction());
				if(tmpB.suivants!=null)	tmpB.suivants.clear();
			}
			int lS  = bBoucle.mesLastNodes.size();
			while(lS!=0){
				Node tmp = bBoucle.mesLastNodes.remove();
				lS -- ;
				//1 creer boucle selon bs avec environ inv2 AND (NOT c)
				Block bBoucleSuivant = new Block(bs,ev);
				if(tmp.suivants!=null) tmp.suivants.add(bBoucleSuivant.mFirstNode);
				//mettre a jour  environement de premier node de block boucle suivant = inv2 AND (NOT c);
				bBoucleSuivant.mFirstNode.environ.listIne.addAll(tmp.invariant.listIne); //first add inv2
				bBoucleSuivant.mFirstNode.environ.listIne.add(c.not()); //then add c
				
				//2 creer un Node avec envrion inv2 AND c invarant inv1
				Node nodeBoucleSuivant = new Node();				
				Invariant invSuiBlockBoucle= new Invariant(bBoucle.mFirstNode.invariant.listIne);
				nodeBoucleSuivant.invariant.listIne.addAll(invSuiBlockBoucle.listIne);
				nodeBoucleSuivant.environ.listIne.addAll(tmp.invariant.listIne);
				nodeBoucleSuivant.environ.listIne.add(c);
				nodeBoucleSuivant.instr = new Instruction(new FaireRienInstruction());
				nodeBoucleSuivant.suivants = null;
				if(tmp.suivants!=null) tmp.suivants.add(nodeBoucleSuivant);
				
				//update mesLastNodes pour block Boucle apres chaque fois creer des sous block
				for(Node toAdd : bBoucleSuivant.mesLastNodes)
					if(!bBoucle.mesLastNodes.contains(toAdd))
						bBoucle.mesLastNodes.add(toAdd);
				bBoucle.mesLastNodes.add(nodeBoucleSuivant);
			}
						
			//update mesLastNodes pour block 
			mesLastNodes.clear();
			mesLastNodes.addAll(bBoucle.mesLastNodes);
			mesLastNodes.addAll(bSuivant.mesLastNodes);
		}

		return;

        
	}

	public Node getmFirstNode(){
		return mFirstNode;
	}
	public void publish(EnsembleVariable ev){
		Node tmp = this.mFirstNode;
		this.publish(tmp,ev);
	}
	
	public void publish(Node n, EnsembleVariable ev){
		LinkedList<Node> visited = new LinkedList<Node>();
		Node tmp = n;
		visited.add(tmp);
		tmp.publish(ev);
		if(tmp.suivants!=null){
			for(Node nn : tmp.suivants){
				if(!visited.contains(nn)) {
					visited.add(nn);
					publish(nn,ev);
				}
			}
		}
	}
}
